const library = require("../library/index.js");
const crypto = require("crypto");
const models = require("../model/user.js");

module.exports = function(lab) {
    return {
        "list": function(session, { start, limit }) {

            if (!session.currentOU || !session.currentUser) {
                throw @lab.errors.not_login;
            }
            // if(session.currentUser.access.indexOf("admin") < 0){
            //     throw @lab.errors.no_permission
            // }

            return lab.query("backend_operators", {
                "conditions": ["ouid = ?","is_bot = ?"],
                "params": [session.currentOU.id,false],
                "start": start,
                "limit": limit,
                "sort" : "create_date asc",
                mapper: (user) => {
                    user.access = user.access ? JSON.parse(user.access) : [];
                    return user;
                }
            });
        },
        @updateAdminStatus : function (session, {id, is_admin}) {
            if (!session.currentOU || !session.currentUser) {
                throw @lab.errors.not_login;
            }

            if (!session.currentUser.is_admin){
                @dump(session.currentUser);
                throw @lab.errors.no_permission;
            }

            if (session.currentUser.id == id) {
                throw new Error("你不能把自己设为管理员");
            }

            return lab.find("backend_operators", {
                id, ouid : session.currentOU.id
            }).then(function(operator) {
                if (!operator) {
                    throw @lab.errors.object_not_found;
                }
                lab.update("backend_operators",operator, {
                    is_admin
                }).pipe(this);
            })
        },
        "markAsAdmin" : function (session, {id}) {
            return lab.backend.users.@updateAdminStatus(session,{id, is_admin : true});
        },
        "unmarkAsAdmin" : function (session, {id}) {
            return lab.backend.users.@updateAdminStatus(session,{id, is_admin : false});
        },
        "newUserAccessKey": function(session, id) {
            if (!session.currentOU || !session.currentUser) {
                throw @lab.errors.not_login;
            }

            return lab.find("backend_operators", {
                id,
                ouid: session.currentOU.id
            }).then(function(operator) {

                if (!operator) {
                    throw @lab.errors.object_not_found;
                }

                lab.backend.keys.@reauth({
                    id: operator.id,
                    name: operator.name,
                    ouid: operator.ouid,
                    ou_name: session.currentOU.name,
                }).then(function(result) {
                    this.next(Buffer.concat([Buffer.from(result.id.split("-").join(""), "hex"), Buffer.from(result.signature, "base64")]).toString("base64"));
                }).pipe(this);
            })
        },
        "save": function(session, { id, name, account, password,ou_type, access, identity }) {

            if (!session.currentOU || !session.currentUser) {
                throw @lab.errors.not_login;
            }
            // if(session.currentUser.access.indexOf("admin") < 0){
            //     throw @lab.errors.no_permission
            // }

            if (!name) {
                throw @lab.errors.invalid_parameters;
            }

            return lab.snapshot(function(snapshot) {

                return @.async(function() {

                    if (id) {

                        snapshot.find("backend_operators", id).then(function(operator) {

                            if (operator) {

                                if (password && password.length < 6) {
                                    throw @lab.errors.invalid_parameters;
                                }
                                let message = ""
                                @.async(function() {

                                    if (password) {
                                        let message = `修改 ${operator.name} 密码`
                                        library.setupPassword(null, operator, password).pipe(this);
                                    } else {
                                        let message = `修改 ${operator.name} 信息 `
                                        this.next(operator);
                                    }

                                }).then(function(updated_operator) {

                                    if (access) {
                                        message += `将权限修改为 ${access.join(",")}\n`
                                    }

                                    if (name !== updated_operator.name) {
                                        message += `将名字修改为 ${name}`
                                    }

                                    snapshot.save("backend_operators", @.merge.advanced(models.backend_operators, updated_operator, {
                                        name: name,
                                        account: account,
                                        access: access || operator.access,
                                        identity: identity || operator.identity || session.currentUser.identity,
                                        is_bot: false,
                                    })).then(function(result) {

                                        @mew.auto("lab.add_operator_log", {
                                            currentUser: session.currentUser,
                                            target: {},
                                            target_id: operator.id,
                                            method: "save",
                                            kitty: "backend.user",
                                            type: "其他",
                                            message
                                        })

                                        if (session.currentUser.id === result.id) {
                                            session.currentUser = library.exportOperator(result);
                                        }
                                        this.next(result)
                                    }).pipe(this);

                                }).pipe(this);

                            } else {
                                throw @lab.errors.object_not_found;
                            }

                        }).pipe(this);

                    } else {

                        if (!(account || account.length < 4)) {
                            throw @lab.errors.invalid_parameters;
                        }

                        if (!(password || password.length < 6)) {
                            throw @lab.errors.invalid_parameters;
                        }

                        snapshot.backend.user.@getByAccount(account).then(function(existing_user) {

                            if (existing_user) {
                                this.reject("user with same account exists");
                            } else {

                                if (session.currentOU && session.currentOU.id) {

                                    snapshot.find("backend_operation_units", session.currentOU.id).pipe(this);

                                } else {

                                    snapshot.backend.ou.saveOU(session, {
                                        "name": name,
                                        "type": ou_type
                                    }).pipe(this);

                                }
                            }

                        }).then(function(created_ou) {

                            ouid = created_ou.id;
                            identity = identity || session.currentUser.identity;

                            library.setupPassword(null, { ouid, name, account, is_bot : false, identity }, password).then(function(updated_operator) {
                                updated_operator.access = access
                                updated_operator.create_date = Date.now();

                                @mew.auto("lab.add_operator_log", {
                                    currentUser: session.currentUser,
                                    target: {},
                                    target_id: updated_operator.id,
                                    method: "save",
                                    kitty: "backend.user",
                                    type: "其他",
                                    message: `创建用户 ${updated_operator.name}`
                                })

                                snapshot.create("backend_operators", updated_operator).pipe(this);
                            }).pipe(this);

                        }).pipe(this);

                    }
                });

            }).then(function(related_operator) {

                process.nextTick(function() {
                    if (id) {
                        @mew.auto("backend.operator_updated", related_operator);
                    } else {
                        @mew.auto("backend.operator_created", related_operator);
                    }
                });

                if (password) {

                }

                this.next(related_operator);

            })
        },
        "@updatePassword": function({ uid, user, password }) {


            if (password && (uid || user)) {

                return @.async(function() {

                    if (user) {
                        this.next(user);
                    } else {
                        lab.find("backend_operators", uid).then(function(operator) {
                            if (operator) {
                                this.next(operator);
                            } else {
                                throw @lab.errors.object_not_found;
                            }
                        }).pipe(this);
                    }

                }).then(function(backend_operator) {

                    library.setupPassword(lab, backend_operator, password).pipe(this);

                });

            } else {
                throw @lab.errors.invalid_parameters;
            }

        },
        "@register": function({ id, name, account, password, ouid, ou_name, ou_type, is_bot = true, access, is_admin = false }) {

            if (!name) {
                throw @lab.errors.empty_name;
            }

            if (!account || !password) {
                throw @lab.errors.empty_field;
            }

            if (account.length < 4) {
                throw @lab.errors.account_length;
            }

            if (password.length < 6) {
                throw @lab.errors.password_length;
            }

            return @.async(function() {

                lab.backend.user.@getByAccount(account).then(function(existing_operator) {

                    if (existing_operator) {
                        throw @lab.errors.account_already_exists;
                    } else {
                        this.next();
                    }

                }).pipe(this);

            }).then(function() {

                if (id) {

                    lab.find("backend_operators", id).then(function(existing_operator) {

                        if (existing_operator) {
                            throw @lab.errors.account_already_exists;
                        } else {
                            this.next();
                        }

                    }).pipe(this);

                } else {
                    this.next();
                }

            }).then(function() {

                lab.snapshot(function(snapshot) {

                    return @.async(function() {

                        if (ouid) {

                            snapshot.find("backend_operation_units", ouid).then(function(ou) {

                                if (ou) {
                                    this.next(ou);
                                } else {
                                    throw @lab.errors.object_not_found;
                                }

                            }).pipe(this);

                        } else if (ou_name) {

                            snapshot.backend.ou.@saveOU({
                                name: ou_name,
                                type: ou_type
                            }).pipe(this);

                        } else {
                            this.next();
                        }

                    }).then(function(ou) {

                        var backend_operator = {
                            id: id,
                            account: account,
                            ouid: ou ? ou.id : undefined,
                            name: name,
                            identity: 0,
                            access: access || [],
                            is_removed: false,
                            is_admin : is_admin ? true : false,
                            is_bot: is_bot ? true : false
                        };

                        @debug("register backend operator");
                        @debug(backend_operator);

                        library.setupPassword(null, backend_operator, password).then(function(updated_operator) {
                            updated_operator.create_date = Date.now();
                            snapshot.create("backend_operators", updated_operator).pipe(this);

                        }).then(function(created_operator) {

                            this.next({
                                user: created_operator,
                                ou: ou
                            });

                        }).pipe(this);

                    });

                }).pipe(this);

            })
        }
    }
}